import json
import httpx
from typing import Any
from mcp.server.fastmcp import FastMCP

# 初始化 MCP 服务
mcp = FastMCP("weatherServer")

# OpenWeather API 配置

OPENWEATHER_API_BASE = ("https://api.openweathermap.org/data/2.5/weather")
API_KEY ="e7da1c0343bd919c3c73eb1cb8e36e6c" # 请替换为你自己的 Openweather API Key
USER_AGENT = "weather-app/1.0"

async def fetch_weather(city: str) -> dict[str, Any] | None:
    """
    从OpenWeather API获取天气信息
    :param city:
    :return: 天气数据字典，若出错返回包含error信息的字典
    """
    params = {
        "q": city,
        "appid": API_KEY,
        "units": "metric",
        "lang": "zh_cn"
    }
    headers = {"User-Agent": USER_AGENT}

    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers, timeout=30)
            response.raise_for_status()
            return response.json()   # 返回字典类型
        except httpx.HTTPError as err:
            return {"error":f"HTTP错误:{err.response.status_code}"}
        except Exception as err:
            return {"error":f"请求失败:{str(err)}"}

def format_weather(data: dict[str, Any]) -> str:
    """
    将天气数据格式化为易读文本
    :param data:  天气数据(可以是字典或JSON字符串)
    :return: 格式化后的天气信息字符串
    """
    if isinstance(data, str):
        try:
            data = json.loads(data)
        except Exception as err:
            return f"无法解析天气数据：{str(err)}"

    # 如果数据中包含错误信息，直接返回错误提示
    if "error" in data:
        return f"!{data['error']}"

    # 提取数据时做容错处理
    city = data.get("name","未知")
    country = data.get("sys",{}).get("country","未知")
    temp = data.get("main",{}).get("temp","N/A")
    humidity = data.get("main",{}).get("humidity","N/A")
    wind_speed = data.get("wind",{}).get("speed","N/A")
    # weather 可能是空列表，因此用[0] 前先提供默认字典
    weather_list = data.get("weather",[{}])
    description = weather_list[0].get("description","未知")

    return (
        f"🌍 {city}, {country}\n"
        f"🌡 温度: {temp}°C\n"
        f"💧 湿度: {humidity}%\n"
        f"🌬 风速: {wind_speed} m/s\n"
        f"🌤 天气: {description}\n"
    )

@mcp.tool()
async def query_weather(city:str) -> str:
    """
    输入指定城市的英文名称，返回今日天气查询结果。
    :param city: 城市名称(英文)
    :return: 格式化后天气信息
    """
    data = await fetch_weather(city)
    return format_weather(data)

if __name__ == '__main__':
    # 以标准I/O方式运行MCP服务
    mcp.run(transport='stdio')


